home *** CD-ROM | disk | FTP | other *** search
- /**
- *
- * Name pcexec -- Load and execute a program
- *
- * Synopsis ercode = pcexec(pfile,pcmd);
- * int ercode Returned DOS 2.0 function error code
- * char *pfile Name of file to load and execute
- * char *pcmd Commmand line to pass to the program
- *
- * Description This function loads and executes the program whose file
- * name is specified with pfile. The program is loaded and
- * executed as if invoked from DOS with the command line
- * specified in pcmd. The spawned program returns control
- * when either execution ends or Ctrl/Break is pressed.
- * A zero error code indicates successful execution; a
- * positive error code reflects an error from the PCSHRINK
- * function, and negative value from the DOS load function
- * EXEC (4b).
- *
- * Returns ercode DOS 2.0 function error code
- *
- * Version 1.1 (C)Copyright Blaise Computing Inc. 1983, 1984
- *
- **/
- #include <compiler.h>
-
- struct segads /* Offset, segment address type */
- {
- unsigned r;
- unsigned s;
- };
- #define ADS struct segads /* Abbreviation */
-
- struct dreg
- {
- unsigned ax,bx,cx,dx,si,di,ds,es;
- };
- #define DOSREG struct dreg
-
- #if LAT200
- extern ADS _psp; /* Program segment prefix */
- #endif
- #if CI201A
- extern ADS _pspseg;
- #endif
- #if LAT104 | CI133D
- extern unsigned _pgmseg;
- #endif
-
- int pcexec(pfile,pcmd)
- char *pfile,*pcmd;
- {
-
- struct parm_block
- {
- unsigned envseg; /* Segment of environment */
- ADS cmd_ads; /* ADS of command line */
- ADS fb1_ads; /* ADS of first and second file */
- ADS fb2_ads; /* control blocks (FCB) */
- } block_val;
- DOSREG dos_reg;
- ADS env_ads,loc_ads;
- int ercode,cmd_len;
- unsigned size,cs,ss,ds,es;
- char *pcmd_line,*calloc();
- #if CI201A & LDATA
- unsigned long ptrtoabs();
- #endif
-
- ercode = pcshrink(&size); /* Release available memory */
- if (ercode != 0)
- return(ercode);
-
- /* First set up the parameter block. Its address is placed in */
- /* BX register when DOS is called. Notice that the double word */
- /* pointers have the offset first then the segment. This is just */
- /* like the ADS type. */
-
- #if LAT104 | CI133D
- env_ads.s = _pgmseg; /* The segment address of the */
- #endif /* environment is at offset 2C */
- #if LAT200 /* in the program segment prefix*/
- env_ads.s = _psp.s;
- #endif
- #if CI201A
- env_ads.s = _pspseg.s;
- #endif
- env_ads.r = 0x2c;
- #if LDATA
- #if CI201A
- loc_ads.s = (unsigned)((ptrtoabs(&block_val.envseg) & 0xffff0L) >> 4L);
- loc_ads.r = (unsigned)(ptrtoabs(&block_val.envseg) & 0xfL);
- #else
- loc_ads.s = (unsigned)(((long)(&block_val.envseg) & 0xffff0L) >> 4L);
- loc_ads.r = (unsigned)((long)(&block_val.envseg) & 0xfL);
- #endif
- #else
- utsreg(&cs,&ss,&ds,&es); /* Return segment reg values */
- loc_ads.s = ds;
- loc_ads.r = &block_val.envseg;
- #endif
- utslmove(&env_ads,&loc_ads,2); /* Copy parent's environment */
-
- /* The command line must have a leading length byte followed by */
- /* actual characters making up the string. */
-
- cmd_len = strlen(pcmd);
- pcmd_line = calloc(cmd_len + 3,1);
- *pcmd_line = (char)cmd_len;
- strcat(pcmd_line,pcmd); /* pcmd_line is in right format*/
- #if LDATA
- #if CI201A
- block_val.cmd_ads.s = (unsigned)((ptrtoabs(pcmd_line) & 0xffff0L) >> 4L);
- block_val.cmd_ads.r = (unsigned)(ptrtoabs(pcmd_line) & 0xfL);
- #else
- block_val.cmd_ads.s = (unsigned)(((long)(pcmd_line) & 0xffff0L) >> 4L);
- block_val.cmd_ads.r = (unsigned)((long)(pcmd_line) & 0xfL);
- #endif
- #else
- block_val.cmd_ads.s = ds;
- block_val.cmd_ads.r = (unsigned)pcmd_line;
- #endif
- block_val.fb1_ads.r = 0x5c; /* FCBs are at 5c and 6c within */
- block_val.fb1_ads.s = env_ads.s; /* the Program Segment Prefix */
- block_val.fb2_ads.r = 0x6c;
- block_val.fb2_ads.s = env_ads.s;
-
- utinit(&dos_reg);
- dos_reg.ax = 0x4b00; /* DOS function call 4b */
- #if LDATA
- #if CI201A
- dos_reg.es = (unsigned)((ptrtoabs(&block_val) & 0xffff0L) >> 4L);
- dos_reg.bx = (unsigned)(ptrtoabs(&block_val) & 0xfL);
- dos_reg.ds = (unsigned)((ptrtoabs(pfile) & 0xffff0L) >> 4L);
- dos_reg.dx = (unsigned)(ptrtoabs(pfile) & 0xfL);
- #else
- dos_reg.es = (unsigned)(((long)(&block_val) & 0xffff0L) >> 4L);
- dos_reg.bx = (unsigned)((long)(&block_val) & 0xfL);
- dos_reg.ds = (unsigned)(((long)(pfile) & 0xffff0L) >> 4L);
- dos_reg.dx = (unsigned)((long)(pfile) & 0xfL);
- #endif
- #else
- dos_reg.bx = (unsigned)&block_val;
- dos_reg.dx = (unsigned)pfile;
- #endif
-
- ercode = -dos(&dos_reg); /* Return negative error code */
- free(pcmd_line);
-
- return(ercode);
-
- }